const Joi = require('joi')
const { HTTP_STATUS, ERROR_CODES } = require('../utils/constants')
const logger = require('../utils/logger')

/**
 * 验证中间件工厂
 */
const validate = (schema, source = 'body') => {
  return (req, res, next) => {
    const data = req[source]
    
    const { error, value } = schema.validate(data, {
      abortEarly: false, // 返回所有错误
      stripUnknown: true, // 移除未知字段
      convert: true // 自动类型转换
    })

    if (error) {
      const errors = error.details.map(detail => ({
        field: detail.path.join('.'),
        message: detail.message,
        value: detail.context?.value
      }))

      logger.warn('Validation failed', {
        source,
        errors,
        ip: req.ip,
        path: req.path
      })

      return res.status(HTTP_STATUS.BAD_REQUEST).json({
        success: false,
        error: {
          code: ERROR_CODES.VALIDATION_ERROR,
          message: '请求参数验证失败',
          details: errors
        }
      })
    }

    // 将验证后的数据替换原始数据
    req[source] = value
    next()
  }
}

/**
 * 用户相关验证模式
 */
const userSchemas = {
  // 用户注册
  register: Joi.object({
    username: Joi.string()
      .alphanum()
      .min(3)
      .max(30)
      .required()
      .messages({
        'string.alphanum': '用户名只能包含字母和数字',
        'string.min': '用户名至少需要3个字符',
        'string.max': '用户名不能超过30个字符',
        'any.required': '用户名是必填项'
      }),
    email: Joi.string()
      .email()
      .required()
      .messages({
        'string.email': '请输入有效的邮箱地址',
        'any.required': '邮箱是必填项'
      }),
    password: Joi.string()
      .min(6)
      .max(128)
      .pattern(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).*$/)
      .required()
      .messages({
        'string.min': '密码至少需要6个字符',
        'string.max': '密码不能超过128个字符',
        'string.pattern.base': '密码必须包含至少一个大写字母、一个小写字母和一个数字',
        'any.required': '密码是必填项'
      }),
    role: Joi.string()
      .valid('student', 'admin')
      .default('student')
      .messages({
        'any.only': '角色只能是student或admin'
      }),
    profile: Joi.object({
      firstName: Joi.string().max(50).allow(''),
      lastName: Joi.string().max(50).allow(''),
      avatar: Joi.string().uri().allow(''),
      phone: Joi.string().pattern(/^[\d\-\+\(\)\s]+$/).allow('')
    }).optional()
  }),

  // 用户登录
  login: Joi.object({
    username: Joi.string().required().messages({
      'any.required': '用户名是必填项'
    }),
    password: Joi.string().required().messages({
      'any.required': '密码是必填项'
    })
  }),

  // 更新用户资料
  updateProfile: Joi.object({
    profile: Joi.object({
      firstName: Joi.string().max(50).allow(''),
      lastName: Joi.string().max(50).allow(''),
      avatar: Joi.string().uri().allow(''),
      phone: Joi.string().pattern(/^[\d\-\+\(\)\s]+$/).allow('')
    }).required()
  }),

  // 更改密码
  changePassword: Joi.object({
    currentPassword: Joi.string().required().messages({
      'any.required': '当前密码是必填项'
    }),
    newPassword: Joi.string()
      .min(6)
      .max(128)
      .pattern(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).*$/)
      .required()
      .messages({
        'string.min': '新密码至少需要6个字符',
        'string.max': '新密码不能超过128个字符',
        'string.pattern.base': '新密码必须包含至少一个大写字母、一个小写字母和一个数字',
        'any.required': '新密码是必填项'
      })
  }),

  // 密码重置请求
  passwordResetRequest: Joi.object({
    email: Joi.string()
      .email()
      .required()
      .messages({
        'string.email': '请输入有效的邮箱地址',
        'any.required': '邮箱是必填项'
      })
  }),

  // 密码重置
  passwordReset: Joi.object({
    token: Joi.string().required().messages({
      'any.required': '重置令牌是必填项'
    }),
    newPassword: Joi.string()
      .min(6)
      .max(128)
      .pattern(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).*$/)
      .required()
      .messages({
        'string.min': '新密码至少需要6个字符',
        'string.max': '新密码不能超过128个字符',
        'string.pattern.base': '新密码必须包含至少一个大写字母、一个小写字母和一个数字',
        'any.required': '新密码是必填项'
      })
  }),

  // 权限检查
  checkPermission: Joi.object({
    permission: Joi.string().required().messages({
      'any.required': '权限名称是必填项'
    }),
    resource: Joi.string().optional()
  })
}

/**
 * AI配置相关验证模式
 */
const aiConfigSchemas = {
  // 创建AI配置
  create: Joi.object({
    name: Joi.string()
      .min(1)
      .max(100)
      .required()
      .messages({
        'string.min': '配置名称不能为空',
        'string.max': '配置名称不能超过100个字符',
        'any.required': '配置名称是必填项'
      }),
    provider: Joi.string()
      .valid('siliconflow', 'openai', 'custom', 'deepseek', 'claude', 'qwen')
      .required()
      .messages({
        'any.only': '服务提供商只能是siliconflow、openai、custom、deepseek、claude或qwen',
        'any.required': '服务提供商是必填项'
      }),
    model: Joi.string()
      .min(1)
      .max(100)
      .required()
      .messages({
        'string.min': '模型名称不能为空',
        'string.max': '模型名称不能超过100个字符',
        'any.required': '模型名称是必填项'
      }),
    apiKey: Joi.string()
      .min(1)
      .max(500)
      .required()
      .messages({
        'string.min': 'API密钥不能为空',
        'string.max': 'API密钥不能超过500个字符',
        'any.required': 'API密钥是必填项'
      }),
    apiUrl: Joi.string()
      .trim()
      .uri()
      .allow('')
      .messages({
        'string.uri': '请输入有效的URL地址'
      }),
    parameters: Joi.object({
      temperature: Joi.number().min(0).max(2).default(0.7),
      maxTokens: Joi.number().min(1).max(8000).default(2000),
      topP: Joi.number().min(0).max(1).default(0.9)
    }).optional()
  }),

  // 更新AI配置
  update: Joi.object({
    name: Joi.string().min(1).max(100),
    provider: Joi.string().valid('siliconflow', 'openai', 'custom', 'deepseek', 'claude', 'qwen'),
    model: Joi.string().min(1).max(100),
    apiKey: Joi.string().min(1).max(500),
    apiUrl: Joi.string().trim().uri().allow(''),
    isActive: Joi.boolean(),
    isDefault: Joi.boolean(),
    parameters: Joi.object({
      temperature: Joi.number().min(0).max(2),
      maxTokens: Joi.number().min(1).max(8000),
      topP: Joi.number().min(0).max(1)
    })
  }).min(1) // 至少需要一个字段
}

/**
 * 聊天会话相关验证模式
 */
const chatSessionSchemas = {
  // 创建会话
  create: Joi.object({
    title: Joi.string().max(200).allow('').default('新对话'),
    aiConfigId: Joi.string().uuid().required().messages({
      'any.required': 'AI配置ID是必填项'
    }),
    systemPrompt: Joi.string().max(2000).allow('').default('')
  }),

  // 更新会话
  update: Joi.object({
    title: Joi.string().max(200),
    systemPrompt: Joi.string().max(2000),
    aiConfigId: Joi.string()
  }).min(1),

  // 添加标签
  addTag: Joi.object({
    tag: Joi.string()
      .min(1)
      .max(50)
      .required()
      .messages({
        'string.min': '标签不能为空',
        'string.max': '标签不能超过50个字符',
        'any.required': '标签是必填项'
      })
  })
}

/**
 * 聊天消息相关验证模式
 */
const chatMessageSchemas = {
  // 发送消息
  send: Joi.object({
    content: Joi.string()
      .min(1)
      .max(10000)
      .required()
      .messages({
        'string.min': '消息内容不能为空',
        'string.max': '消息内容不能超过10000个字符',
        'any.required': '消息内容是必填项'
      }),
    role: Joi.string().valid('user', 'assistant').default('user'),
    aiConfigId: Joi.string().allow(null).optional()
  }),

  // 编辑消息
  edit: Joi.object({
    content: Joi.string()
      .min(1)
      .max(10000)
      .required()
      .messages({
        'string.min': '消息内容不能为空',
        'string.max': '消息内容不能超过10000个字符',
        'any.required': '消息内容是必填项'
      })
  }),

  // 添加反应
  addReaction: Joi.object({
    type: Joi.string()
      .valid('like', 'dislike', 'love', 'laugh', 'angry', 'sad')
      .required()
      .messages({
        'any.only': '反应类型无效',
        'any.required': '反应类型是必填项'
      })
  })
}

/**
 * 系统配置相关验证模式
 */
const systemConfigSchemas = {
  // 设置配置
  set: Joi.object({
    key: Joi.string()
      .min(1)
      .max(100)
      .required()
      .messages({
        'string.min': '配置键不能为空',
        'string.max': '配置键不能超过100个字符',
        'any.required': '配置键是必填项'
      }),
    value: Joi.any().required().messages({
      'any.required': '配置值是必填项'
    }),
    type: Joi.string()
      .valid('string', 'number', 'boolean', 'json', 'email', 'url')
      .default('string'),
    description: Joi.string().max(500).allow(''),
    category: Joi.string().max(50).default('general'),
    isPublic: Joi.boolean().default(false)
  }),

  // 批量设置配置
  setBatch: Joi.object({
    configs: Joi.array().items(
      Joi.object({
        key: Joi.string().min(1).max(100).required(),
        value: Joi.any().required(),
        options: Joi.object({
          type: Joi.string().valid('string', 'number', 'boolean', 'json', 'email', 'url').default('string'),
          description: Joi.string().max(500).allow(''),
          category: Joi.string().max(50).default('general'),
          isPublic: Joi.boolean().default(false)
        }).optional()
      })
    ).min(1).required().messages({
      'array.min': '至少需要一个配置项',
      'any.required': '配置列表是必填项'
    })
  })
}

/**
 * 分页参数验证模式
 */
const paginationSchema = Joi.object({
  page: Joi.number().integer().min(1).default(1),
  limit: Joi.number().integer().min(1).max(100).default(20),
  search: Joi.string().max(200).allow(''),
  sortBy: Joi.string().max(50).allow(''),
  sortOrder: Joi.string().valid('asc', 'desc').default('desc')
})

/**
 * ID参数验证模式
 */
const idSchema = Joi.object({
  id: Joi.string().required().messages({
    'any.required': 'ID参数是必填项'
  })
})

/**
 * 刷新令牌验证模式
 */
const refreshTokenSchema = Joi.object({
  refreshToken: Joi.string().required().messages({
    'any.required': '刷新令牌是必填项'
  })
})

/**
 * 搜索参数验证模式
 */
const searchSchema = Joi.object({
  query: Joi.string()
    .min(1)
    .max(200)
    .required()
    .messages({
      'string.min': '搜索关键词不能为空',
      'string.max': '搜索关键词不能超过200个字符',
      'any.required': '搜索关键词是必填项'
    }),
  limit: Joi.number().integer().min(1).max(50).default(10)
})

/**
 * Express-validator 验证请求中间件
 */
const { validationResult } = require('express-validator')

const validateRequest = (req, res, next) => {
  const errors = validationResult(req)
  if (!errors.isEmpty()) {
    return res.status(HTTP_STATUS.BAD_REQUEST).json({
      success: false,
      error: {
        code: ERROR_CODES.VALIDATION_ERROR,
        message: '请求参数验证失败',
        details: errors.array()
      }
    })
  }
  next()
}

/**
 * 导出验证中间件
 */
module.exports = {
  validate,
  validateRequest,
  
  // 用户验证
  validateUserRegister: validate(userSchemas.register),
  validateUserLogin: validate(userSchemas.login),
  validateUserUpdateProfile: validate(userSchemas.updateProfile),
  validateUserChangePassword: validate(userSchemas.changePassword),
  validatePasswordResetRequest: validate(userSchemas.passwordResetRequest),
  validatePasswordReset: validate(userSchemas.passwordReset),
  validateCheckPermission: validate(userSchemas.checkPermission),
  
  // AI配置验证
  validateAiConfigCreate: validate(aiConfigSchemas.create),
  validateAiConfigUpdate: validate(aiConfigSchemas.update),
  
  // 聊天会话验证
  validateChatSessionCreate: validate(chatSessionSchemas.create),
  validateChatSessionUpdate: validate(chatSessionSchemas.update),
  validateChatSessionAddTag: validate(chatSessionSchemas.addTag),
  
  // 聊天消息验证
  validateChatMessageSend: validate(chatMessageSchemas.send),
  validateChatMessageEdit: validate(chatMessageSchemas.edit),
  validateChatMessageAddReaction: validate(chatMessageSchemas.addReaction),
  
  // 系统配置验证
  validateSystemConfigSet: validate(systemConfigSchemas.set),
  validateSystemConfigSetBatch: validate(systemConfigSchemas.setBatch),
  
  // 通用验证
  validatePagination: validate(paginationSchema, 'query'),
  validateId: validate(idSchema, 'params'),
  validateRefreshToken: validate(refreshTokenSchema),
  validateSearch: validate(searchSchema, 'query'),
  
  // 原始验证模式（供自定义使用）
  schemas: {
    user: userSchemas,
    aiConfig: aiConfigSchemas,
    chatSession: chatSessionSchemas,
    chatMessage: chatMessageSchemas,
    systemConfig: systemConfigSchemas,
    pagination: paginationSchema,
    id: idSchema,
    refreshToken: refreshTokenSchema,
    search: searchSchema
  }
}